package com.tankwar.transport;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

import com.google.common.collect.Lists;
import com.swak.Constants;
import com.swak.OS;
import com.swak.exception.RpcException;
import com.swak.reactivex.threads.Contexts;
import com.swak.reactivex.transport.TransportMode;
import com.swak.reactivex.transport.resources.LoopResources;
import com.swak.registry.URL;
import com.swak.utils.Maps;

import lombok.Getter;

/**
 * 传输协议
 * 
 * @author 618lf
 */
public class Transports implements DisposableBean, InitializingBean {

	private static final int Port = 10888;

	private static final LoopResources resources = Contexts.createEventLoopResources(TransportMode.OS, 1, 2,
			"Tankwar.EventLoop-", false, 2, TimeUnit.SECONDS);

	private List<TankwarClient> clients = Lists.newCopyOnWriteArrayList();
	private Lock lock = new ReentrantLock();
	private TankwarServer server;

	@Getter
	private URL url;

	@Override
	public void afterPropertiesSet() throws Exception {
		Map<String, String> params = Maps.newHashMap();
		//params.put(Constants.Bind_Host, Constants.ANYHOST);
		params.put(Constants.Category_Key, "server");
		this.url = new URL("tankwar", "127.0.0.1", Port, params);
	}

	/**
	 * 发布服务
	 * 
	 * @param cmds
	 */
	public void startServer() {
		lock.lock();
		try {

			// 支持的命令
			this.server = this.newServer(url);
			this.server.start();

			// 显示服务
		} finally {
			lock.unlock();
		}
	}

	@Override
	public void destroy() throws Exception {
		try {
			if (server != null) {
				server.close();
			}
		} catch (Exception e) {
		}
		try {
			for (TankwarClient client : clients) {
				client.close();
			}
		} catch (Exception e) {
		}
	}

	private TankwarServer newServer(URL url) {
		return new TankwarServer(url, resources);
	}

	public TankwarClient newClient(URL url) {
		try {
			TankwarClient client = new TankwarClient(url, resources);
			url.addParameter(Constants.Heartbeat, String.valueOf(Constants.Default_Heartbeat));
			this.clients.add(client);
			return client;
		} catch (Exception e) {
			throw new RpcException(RpcException.UNKNOWN_EXCEPTION,
					"Fail to create remoting client for service(" + url + "): " + e.getMessage(), e);
		}
	}
}